package com.example.mapperapi.file;

import com.example.mapperapi.annotation.MapperFileTo;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.binary.Base64;
import org.springframework.stereotype.Component;

import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;

@Component
@Slf4j
public class FileUtil {


    private final Map<String, String> fileMap;
    private final AtomicInteger atomicInteger = new AtomicInteger();

    {
        fileMap = new ConcurrentHashMap<String, String>(20);
    }

    public String getFileIndex() {
        int i = atomicInteger.incrementAndGet();
        return System.currentTimeMillis() + "" + i;
    }

    public void put(String fileIndex, String fileStr) {
        fileMap.put(fileIndex, fileStr);
    }

    public byte[] getBytes(String fileIndex) {
        return Base64.decodeBase64(fileMap.get(fileIndex));
    }

    public String getString(String fileIndex) {
        return fileMap.get(fileIndex);
    }

    public void remove(String fileIndex) {
        fileMap.remove(fileIndex);
    }


    public void mapperTo(Object source, Object target, String prefix) {
        HashMap<String, Object> targetMap = new HashMap<>();
        for (Field field : target.getClass().getDeclaredFields()) {
            field.setAccessible(true);
            targetMap.put(field.getName(), field);
        }
        for (Field field : source.getClass().getDeclaredFields()) {
            field.setAccessible(true);
            if (field.isAnnotationPresent(MapperFileTo.class)) {
                try {
                    String value = field.getAnnotation(MapperFileTo.class).value();
                    Field targetField = (Field) targetMap.get(value);
                    if (targetField != null && String.class.equals(targetField.getType())) {
                        if (String.class.equals(field.getType())) {
                            doMapperFileTo((String) field.get(source), targetField, target, prefix);
                        } else if (byte[].class.equals(field.getType())) {
                            String string = Base64.encodeBase64String((byte[]) field.get(source));
                            doMapperFileTo(string, targetField, target, prefix);
                        }
                    }
                } catch (Exception e) {
                    log.error(e.getMessage());
                    log.error("doMapperFileToError!{}", field.getName());
                }
            }
        }
    }


    /**
     * 将文件类型字段映射为url到目标字段
     *
     * @param sourceObj   源obj
     * @param targetField 目标字段
     * @param target      目标
     */
    private void doMapperFileTo(String sourceObj, Field targetField, Object target, String prefix) {
        try {
            String fileIndex = getFileIndex();
            fileMap.put(fileIndex, sourceObj);
            String url = prefix + fileIndex;
            targetField.set(target, url);
        } catch (Exception e) {
            log.error(e.getMessage());
            log.error("doMapperFileToError!{}", targetField.getName());
        }
    }
}
